package com.ninong.ker.common.auth;

import java.security.Key;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

import javax.servlet.http.HttpServletRequest;

import com.ninong.ker.common.tools.CmdAdminTools;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;

import com.alibaba.fastjson.JSONObject;
import com.ninong.ker.common.tools.RedisUtils;
import com.ninong.ker.common.user.OnlineUser;

import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.UUID;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.io.Decoders;
import io.jsonwebtoken.security.Keys;

/**
 * 安全管理文件
 *
 * @author cmd
 */
@Component
public class SecurityAdmin implements InitializingBean {

    private final JwtProperties properties;
    private Key key;
    private RedisUtils redisUtils;
    @Autowired
    private RedisTemplate<Object, Object> redisTemplate;

    public SecurityAdmin(JwtProperties properties, RedisUtils redisUtils) {
        this.properties = properties;
        this.redisUtils = redisUtils;
    }

    @Override
    public void afterPropertiesSet() {
        byte[] keyBytes = Decoders.BASE64.decode(properties.getSecret());
        this.key = Keys.hmacShaKeyFor(keyBytes);
    }

    /**
     * 生成token
     *
     * @param login
     * @return
     */
    public String createToken(String login) {
        return Jwts.builder().setSubject(login)
                .signWith(key, SignatureAlgorithm.HS512)
                // 加入ID确保生成的 Token 都不一致
                .setId(UUID.randomUUID().toString()).compact();
    }

    /**
     * 续时token
     */
    public void checkRenewal(String token) {
        redisTemplate.expire(properties.getOnline() + token, properties.getValidity()/1000, TimeUnit.SECONDS);
    }

    /**
     * 获取当前登录用户
     *
     * @param token
     * @return
     */
    public OnlineUser currentUser(String token) {
        Object tokens = redisUtils.get(properties.getOnline() + token);
        if (!ObjectUtils.isEmpty(tokens)) {
            String login = tokens.toString();
            return JSONObject.parseObject(login, OnlineUser.class);
        } else {
            return null;
        }
    }

    /**
     * 获取当前登录用户
     * @return
     */
    public OnlineUser currentUser() {
        HttpServletRequest request = CmdAdminTools.getHttpServletRequest();
        String token = this.getToken(request);
        Object tokens = redisUtils.get(properties.getOnline() + token);
        if (!ObjectUtils.isEmpty(tokens)) {
            String login = tokens.toString();
            return JSONObject.parseObject(login, OnlineUser.class);
        } else {
            return null;
        }
    }

    /**
     * 获取当前登录用户
     *
     * @param token
     * @return
     */
    @SuppressWarnings("unchecked")
    public List<String> getAuthorities(String token) {
        OnlineUser online = currentUser(token);
        String login = redisUtils.get("ROLES-"+online.getId()).toString();
        JSONObject json = JSONObject.parseObject(login);
        return (List<String>) json.get("roles");
    }

    /**
     * 校验token
     *
     * @param authToken
     * @return
     */
    public boolean validateToken(String authToken) {
        Object token = redisTemplate.opsForValue().get(properties.getOnline() + authToken);
        if (!ObjectUtils.isEmpty(token)) {
            return true;
        }
        return false;
    }

    /**
     * 获取token
     *
     * @param request
     * @return
     */
    public String getToken(ServerHttpRequest request) {
        final String requestHeader = request.getHeaders().getFirst(properties.getHeader());
        return requestHeader;
    }

    /**
     * 获取token
     * @return
     */
    public String getToken() {
        HttpServletRequest request = CmdAdminTools.getHttpServletRequest();
        final String requestHeader = request.getHeader(properties.getHeader());
        return requestHeader;
    }

    /**
     * 获取token
     *
     * @param request
     * @return
     */
    public String getToken(HttpServletRequest request) {
        final String requestHeader = request.getHeader(properties.getHeader());
        return requestHeader;
    }

    /**
     * 是否开启接口校验
     *
     * @return
     */
    public Boolean getAuth() {
        return properties.getSecurity();
    }

    /**
     * 获取缓存中的字典集合
     *
     * @return
     */
    public Object getDics(String key) {
        return redisUtils.get(key);
    }
}
